#include "inst.h"
#include "type.h"

namespace hua
{
    #define max(a, b) ((a)>(b) ? (a) : (b))

	static unsigned char toFamily(unsigned char ucCmd, unsigned char ucDataType = 0)
    {
    
        return 0;
    }

    Operand::Operand(unsigned char ucDataType, unsigned char ucAddition, int iVariable)
        : m_ucDataType(ucDataType), m_ucAddition(ucAddition), m_iVariable(iVariable)
    {
        
    }
    
    Operand Operand::operator &()
	{
        if(m_ucAddition == REAL) // &(*p) -> p
            return Operand(VIRTUAL, PVOID, m_iVariable);
        
        if(m_ucAddition == VIRTUAL) // &(v)
            return Operand(LA_VIRTUAL, PVOID, m_iVariable);
            
        return Operand(CONST, INT, 0); // constant 0
	}
    
    Inst::Inst(unsigned char cmd)
        : m_ucCmd(cmd), m_ucFamily(toFamily(cmd))
	{
        m_oOperandAttribute[0].m_ucDataType = 0;
        m_oOperandAttribute[0].m_ucAddition = 0;
        
        m_oOperandAttribute[1].m_ucDataType = 0;
        m_oOperandAttribute[1].m_ucAddition = 0;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = 0;
        m_iOperandVariable[1] = 0;
        m_iOperandVariable[2] = 0;
	}

	Inst::Inst(unsigned char cmd, Operand a)
        : m_ucCmd(cmd), m_ucFamily(toFamily(cmd))
	{
		m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = 0;
        m_oOperandAttribute[1].m_ucAddition = 0;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = 0;
        m_iOperandVariable[2] = 0;
	}

	Inst::Inst(unsigned char cmd, Operand a, Operand b)
        : m_ucCmd(cmd), m_ucFamily(toFamily(cmd, b.m_ucDataType))
	{
		m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = b.m_ucDataType;
        m_oOperandAttribute[1].m_ucAddition = b.m_ucAddition;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = b.m_iVariable;
        m_iOperandVariable[2] = 0;
	}

	Inst::Inst(unsigned char cmd, Operand a, Operand b, Operand c)
        : m_ucCmd(cmd), m_ucFamily(toFamily(cmd, max(b.m_ucDataType, c.m_ucDataType)))
	{
		m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = b.m_ucDataType;
        m_oOperandAttribute[1].m_ucAddition = b.m_ucAddition;
        
        m_oOperandAttribute[2].m_ucDataType = c.m_ucDataType;
        m_oOperandAttribute[2].m_ucAddition = c.m_ucAddition;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = b.m_iVariable;
        m_iOperandVariable[2] = c.m_iVariable;
	}

	Inst& Inst::operator()(unsigned char cmd)
	{
		m_ucCmd = cmd;
        m_ucFamily = toFamily(cmd);
        
        m_oOperandAttribute[0].m_ucDataType = 0;
        m_oOperandAttribute[0].m_ucAddition = 0;
        
        m_oOperandAttribute[1].m_ucDataType = 0;
        m_oOperandAttribute[1].m_ucAddition = 0;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = 0;
        m_iOperandVariable[1] = 0;
        m_iOperandVariable[2] = 0;
        
        return *this;
	}

	Inst& Inst::operator()(unsigned char cmd, Operand a)
	{
		m_ucCmd = cmd;
        m_ucFamily = toFamily(cmd);
        
        m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = 0;
        m_oOperandAttribute[1].m_ucAddition = 0;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = 0;
        m_iOperandVariable[2] = 0;
        
        return *this;
	}

	Inst& Inst::operator()(unsigned char cmd, Operand a, Operand b)
	{
		m_ucCmd = cmd;
        m_ucFamily = toFamily(cmd, b.m_ucDataType);
        
        m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = b.m_ucDataType;
        m_oOperandAttribute[1].m_ucAddition = b.m_ucAddition;
        
        m_oOperandAttribute[2].m_ucDataType = 0;
        m_oOperandAttribute[2].m_ucAddition = 0;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = b.m_iVariable;
        m_iOperandVariable[2] = 0;
        
        return *this;
	}

	Inst& Inst::operator()(unsigned char cmd, Operand a, Operand b, Operand c)
	{
		m_ucCmd = cmd;
        m_ucFamily = toFamily(cmd, max(b.m_ucDataType, c.m_ucDataType));
        
        m_oOperandAttribute[0].m_ucDataType = a.m_ucDataType;
        m_oOperandAttribute[0].m_ucAddition = a.m_ucAddition;
        
        m_oOperandAttribute[1].m_ucDataType = b.m_ucDataType;
        m_oOperandAttribute[1].m_ucAddition = b.m_ucAddition;
        
        m_oOperandAttribute[2].m_ucDataType = c.m_ucDataType;
        m_oOperandAttribute[2].m_ucAddition = c.m_ucDataType;
        
        m_iOperandVariable[0] = a.m_iVariable;
        m_iOperandVariable[1] = b.m_iVariable;
        m_iOperandVariable[2] = c.m_iVariable;
        
        return *this;
	}
}